package stardust.product.platform.persistence.transaction;


import java.sql.Connection;
import java.sql.SQLException;
import stardust.product.platform.persistence.PersistenceException;


public class TransactionObject
{
	
	private String transactionName;
	private Connection connection;

	private TransactionManager transactionManager;
	private TransactionProperties transactionProperties;
	private TransactionObject beforeTransaction;
	
	public TransactionObject(TransactionManager transactionManager, TransactionProperties transactionProperties)
	{
		this.transactionManager = transactionManager;
		this.transactionProperties = transactionProperties;
	}
	
	public void begin() throws PersistenceException, SQLException
	{
		if (this.connection != null)
		{
			throw new PersistenceException("事务已经开启。");
		}
		
		this.beforeTransaction = this.transactionManager.getTransaction();
		
		if (transactionProperties.getType() == TransactionType.NotSupported)
		{
			if (this.beforeTransaction != null)
			{
				if (this.beforeTransaction.transactionProperties.getType() == TransactionType.NotSupported)
				{
					// 如果上一个事务为不支持的将继承连接。
					this.extendConnection();
				}
				else
				{
					this.newConnection();
				}
			}
			else
			{
				// 如果没有前期事务将开启新连接。
				this.newConnection();
			}
		}
		else if (transactionProperties.getType() == TransactionType.Supports)
		{
			if (this.beforeTransaction != null)
			{
				if (this.beforeTransaction.transactionProperties.getType() == TransactionType.NotSupported ||
					this.beforeTransaction.transactionProperties.getType() == TransactionType.Isolated)
				{
					// 如果上一个事务为不支持的或孤立的将开启新连接。
					this.newConnection();
				}
				else
				{
					this.extendConnection();
				}
			}
			else
			{
				// 如果没有前期事务将开启新连接。
				this.newConnection();
			}
		}
		else if (transactionProperties.getType() == TransactionType.RequiresNew)
		{
			// 无论上一个事务是什么，使用新连接进行事务控制。
			this.newConnection();
		}
		else if (transactionProperties.getType() == TransactionType.Isolated)
		{
			// 无论上一个事务是什么，使用新连接进行事务控制。（注意：与RequiresNew不同的是，此类型的事务无法被子程序继承使用，它始终是孤立的。）
			this.newConnection();
		}
		
		if (this.connection == null)
		{
			throw new PersistenceException("没有数据连接，无法开启事务。");
		}
		
		// 分配好数据连接后生成事务名称并向事务管理器注册。
		this.transactionName = "tx_" + (System.currentTimeMillis() + this.hashCode());
		this.transactionManager.registerTransaction(this);
		
		this.transactionManager.getDataAccessFactory().createDataAccess().createJdbcHelper().execute
		(
			this.transactionManager.getDataAccessFactory().getSqlFactory().beginTransaction(this.getTransactionName())
		);
	}
	
	public void commit() throws PersistenceException, SQLException
	{
		if (this.connection == null)
		{
			throw new PersistenceException("事务未开启。");
		}
		else if (this.transactionManager.getTransaction() != this)
		{
			throw new PersistenceException("禁止跨越作用域提交事务。");
		}
		
		if (this.transactionProperties.getType() == TransactionType.NotSupported)
		{
			// 不支持的事务总是立刻回滚。
			this.transactionManager.getDataAccessFactory().createDataAccess().createJdbcHelper().execute
			(
				this.transactionManager.getDataAccessFactory().getSqlFactory().rollbackTransaction(this.getTransactionName())
			);
		}
		else if (this.transactionProperties.getType() == TransactionType.Isolated)
		{
			// 孤立的事务总是立刻提交。
			this.transactionManager.getDataAccessFactory().createDataAccess().createJdbcHelper().execute
			(
				this.transactionManager.getDataAccessFactory().getSqlFactory().commitTransaction(this.getTransactionName())
			);
		}
		else
		{
			if (this.beforeTransaction == null || (this.connection != this.beforeTransaction.getConnection()))
			{
				// 提交事务。
				this.transactionManager.getDataAccessFactory().createDataAccess().createJdbcHelper().execute
				(
					this.transactionManager.getDataAccessFactory().getSqlFactory().commitTransaction(this.getTransactionName())
				);
			}
		}
		
		/*
		 * 当前事务销毁后已经跨越事务作用域或者事务已经结束时将关闭数据连接。
		 */
		if (this.beforeTransaction == null || (this.connection != this.beforeTransaction.getConnection()))
		{
			this.connection.close();
		}
		
		this.connection = null;
		this.transactionManager.deregisterTransaction();
	}
	
	public void rollback() throws PersistenceException, SQLException
	{
		if (this.connection == null)
		{
//			throw new PersistenceException("事务未开启。");
		  return;
		}
		else if (this.transactionManager.getTransaction() != this)
		{
			throw new PersistenceException("禁止跨越作用域回滚事务。");
		}
		
		this.transactionManager.getDataAccessFactory().createDataAccess().createJdbcHelper().execute
		(
			this.transactionManager.getDataAccessFactory().getSqlFactory().rollbackTransaction(this.getTransactionName())
		);
		
		/*
		 * 当前事务销毁后已经跨越事务作用域或者事务已经结束时将关闭数据连接。
		 */
		if (this.beforeTransaction == null || (this.connection != this.beforeTransaction.getConnection()))
		{
			this.connection.close();
		}

		this.connection = null;
		this.transactionManager.deregisterTransaction();
	}
	
	private void newConnection() throws SQLException
	{
		this.connection = this.transactionManager.getDataAccessFactory().getDataSource().getConnection();
		this.connection.setAutoCommit(false);
	}
	
	private void extendConnection()
	{
		this.connection = this.beforeTransaction.getConnection();
	}
	
	public String getTransactionName()
	{
		return this.transactionName;
	}
	
	public Connection getConnection()
	{
		return this.connection;
	}
	
}
